package com.homework;

import com.homework.encoder.RpcEncoder;
import com.homework.pojo.RpcRequest;
import com.homework.service.UserService;
import com.homework.serviceImpl.JSONSerializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;

import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RpcConsumer {

    private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    private static UserClientHandler clientHandler;

    private static ChannelFuture sync;

    public Object createProxy(final Class<?> serviceClass,final String port){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class<?>[]{serviceClass},((proxy,method,args) -> {
            if (clientHandler == null){
                initClient(port);
            }
            RpcRequest rpcRequest = new RpcRequest();

            rpcRequest.setRequestId(UUID.randomUUID().toString());
            rpcRequest.setClassName(method.getDeclaringClass().getName());
            rpcRequest.setMethodName(method.getName());
            rpcRequest.setParameters(args);
            Class<?>[] parameterTypes = method.getParameterTypes();
            rpcRequest.setParameterTypes(parameterTypes);
            //设置参数
            clientHandler.setPara(rpcRequest);
            return executorService.submit(clientHandler).get();
        }));
    }

    public void close(){
        if (sync != null){
            sync.channel().close();
        }
    }
    private void initClient(String port) throws InterruptedException{
        clientHandler = new UserClientHandler();
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group).channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY,true)
                .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline pipeline = socketChannel.pipeline();
                pipeline.addLast(new RpcEncoder(UserService.class,new JSONSerializer()));
                pipeline.addLast(new StringDecoder());
                pipeline.addLast(clientHandler);
            }
        });
        sync = bootstrap.connect("127.0.0.1", Integer.parseInt(port)).sync();
    }
}
